package cn.itsource.ymcc.service.impl;

import cn.itsource.ymcc.constant.ErrorConstantCode;
import cn.itsource.ymcc.constant.RedisConstants;
import cn.itsource.ymcc.domain.Login;
import cn.itsource.ymcc.domain.User;
import cn.itsource.ymcc.domain.UserAccount;
import cn.itsource.ymcc.domain.UserBaseInfo;
import cn.itsource.ymcc.dto.UserRegisterDTO;
import cn.itsource.ymcc.dto.VerifyCodeDTO;
import cn.itsource.ymcc.feignclient.LoginFeignclient;
import cn.itsource.ymcc.mapper.UserMapper;
import cn.itsource.ymcc.result.JSONResult;
import cn.itsource.ymcc.service.IUserAccountService;
import cn.itsource.ymcc.service.IUserBaseInfoService;
import cn.itsource.ymcc.service.IUserService;
import cn.itsource.ymcc.util.AssertUtil;
import cn.itsource.ymcc.util.BitStatesUtils;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.sun.javafx.binding.StringFormatter;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.xml.crypto.Data;
import java.math.BigDecimal;
import java.util.Date;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author gwk
 * @since 2023-02-19
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;


    @Autowired
    public LoginFeignclient loginFeignclient;

    @Autowired
    public IUserAccountService accountService;

    @Autowired
    public IUserBaseInfoService baseInfoService;

    /**
     * // 用户注册
     * @param userdto
     */
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    //@Transactional(propagation= Propagation.REQUIRED,readOnly = false)
    public void register(UserRegisterDTO userdto) {
        //1.1 参数校验，非空了，合法 -- JSR303
        String mobile = userdto.getMobile();
        String password = userdto.getPassword();
        Integer regChannel = userdto.getRegChannel();
        String smsCode = userdto.getSmsCode();


        //1.2 判断短信验证码
        verifyCodeTest(mobile, smsCode);

        //2.1 查询手机号是否已经被注册 baseMapper mybatisPlus 提供查询 mapper 条件构造器wrapper
        User user = getUser(mobile);


        //2.2 封装login对象，调用uaaFeign接口，保存到t_login 表
        //保存到t_user ,同时保存login_id
        Long loginId = getLoginID(mobile, password);

        //3.为要保存的User对象
        saveUser(mobile, loginId);

    }

    /**
     * 保存 t_user t_user_account t_baseinfo
     * @param mobile
     * @param loginId
     */

    private void saveUser(String mobile, Long loginId) {
        User user;
        user = new User();
        Date date = new Date();
        user.setCreateTime(date.getTime());
        user.setPhone(mobile);
        user.setNickName(mobile);
        Long state = BitStatesUtils.addState(BitStatesUtils.OP_REGISTED,BitStatesUtils.OP_AUTHED_PHONE);
        user.setBitState(state);
        user.setLoginId(loginId);

        insert(user);
        //获取user_id
        //t_user_account，t_user_base_info，同时开户
        UserAccount account = new UserAccount();
        account.setId(user.getId());
        account.setFrozenAmount(new BigDecimal(0));
        account.setUsableAmount(new BigDecimal(0));
        account.setCreateTime(date.getTime());
        account.setPassword(null);

        accountService.insert(account);

        int i = 1/0;

        UserBaseInfo baseInfo = new UserBaseInfo();
        baseInfo.setId(user.getId());
        baseInfo.setCreateTime(date.getTime());
        baseInfo.setRegChannel(1);

        baseInfoService.insert(baseInfo);
    }

    private Long getLoginID(String mobile, String password) {
        Login login = new Login();
        login.setUsername(mobile);
        login.setPassword(password);
        login.setType(1);
        JSONResult jsonResult = loginFeignclient.saveOrUpdate(login);
        //保存成功获取 login_id
        Long loginId = Long.valueOf(jsonResult.getData().toString());
        return loginId;
    }

    private User getUser(String mobile) {
        Wrapper<User> wapper =  new EntityWrapper<>();
        wapper.eq("phone", mobile); // select * from t_user where phone = #{mobile}
        User user = selectOne(wapper);

        //没有注册的手机，才继续
        AssertUtil.isNull(user,ErrorConstantCode.PHONE_HAS_REGISTERED);
        return user;
    }

    /**
     * 验证短信验证码
     * @param mobile
     * @param smsCode
     */
    private void verifyCodeTest(String mobile, String smsCode) {
        String key = String.format(RedisConstants.SMS_REGISTER_KEY, mobile);
        // 从redis里获取验证码
        VerifyCodeDTO verifyCodeDTO = (VerifyCodeDTO)redisTemplate.opsForValue().get(key);
        // 验证码获取不到
        AssertUtil.isNotNull(verifyCodeDTO,ErrorConstantCode.PARAMETER_NOT_BE_NULL);

        // 断言比较
        AssertUtil.isEquals(smsCode,verifyCodeDTO.getVerifyCode(), ErrorConstantCode.VEROIFYCODE_IS_NULL);
    }
}
